package com.flyxiaozhu.erp.admin.controllers;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.flyxiaozhu.erp.admin.authorize.AuthorizeHelper;
import com.flyxiaozhu.erp.admin.resps.GoodsResp;
import com.flyxiaozhu.erp.admin.resps.SchemaResp;
import com.flyxiaozhu.erp.core.entities.*;
import com.flyxiaozhu.erp.core.helper.DateHelper;
import com.flyxiaozhu.erp.core.helper.RandomStringGenerateHelper;
import com.flyxiaozhu.erp.core.libs.*;
import com.flyxiaozhu.erp.core.pojos.GoodsTagsPojo;
import com.flyxiaozhu.erp.core.repositories.*;
import com.flyxiaozhu.erp.core.services.GoodsCategoryService;
import com.flyxiaozhu.erp.core.services.GoodsService;
import com.flyxiaozhu.erp.core.services.GoodsSkuService;
import com.flyxiaozhu.erp.core.utils.BeanUtils;
import com.flyxiaozhu.erp.core.utils.CollectionUtils;
import com.flyxiaozhu.erp.core.utils.OSSClientUtils;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.security.access.annotation.Secured;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.*;

/**
 * @author flyxiaozhu
 * @date 2019-04-14 15:36
 */
@RestController
@Slf4j
public class GoodsController {

    @Autowired
    GoodsRepository goodsRepository;
    @Autowired
    GoodsCategoryService goodsCategoryService;
    @Autowired
    GoodsTagRepository goodsTagRepository;
    @Autowired
    GoodsStockLogRepository goodsStockLogRepository;
    @Autowired
    GoodsService goodsService;
    @Autowired
    GoodsAttrNameRepository goodsAttrNameRepository;
    @Autowired
    GoodsSkuRepository goodsSkuRepository;
    @Autowired
    GoodsSkuService goodsSkuService;

    @Value("${oss.endpoint}")
    private String ENDPOINT;
    @Value("${oss.accessKeyId}")
    private String ACCESS_KEY_ID;
    @Value("${oss.accessKeySecret}")
    private String ACCESS_KEY_SECRET;
    @Value("${oss.bucketName}")
    private String BUCKET_NAME;
    @Value("${oss.fileDir}")
    private String FILE_DIR;

    @RequestMapping(value = "/goods/select")
    @Secured("ROLE_GOODS_SELECT")
    public JSONResult goodsList(HttpServletRequest request, @PageableDefault(sort = {"updateTime", "createTime"}, direction = Sort.Direction.DESC) Pageable pageable) {
        SearchSpecification<Goods> searchSpecification = new SearchSpecification<>(request);

        searchSpecification.setBeforeFilter((list, root, query, cb) -> {
            list.add(cb.equal(root.get("isDeleted"), false));
        });
        searchSpecification.setFilter("search_eq_tagsId", (list, field, operator, value, root, query, cb) -> {
                    List<GoodsTagsPojo> pojos = goodsTagRepository.getTagedGoodsByTagsId(Long.parseLong(value));
                    if (pojos.size() != 0) {
                        List<Long> tagedGoodsIds = CollectionUtils.map(pojos, GoodsTagsPojo::getGoodsId);
                        return cb.in(root.get("id")).value(tagedGoodsIds);
                    }
                    return cb.equal(root.get("id"), 0);
                }
        );

        Page<Goods> goodsPage = goodsRepository.findAll(searchSpecification, pageable);

        if (goodsPage.getContent().size() == 0) {
            return new JSONResult().put("list", new ArrayList<>());
        }

        Map<Long, List<GoodsSku>> skusGroupByGoodsId = goodsSkuService.findByGoodsIdGroup();

        List<GoodsResp> resps = new ArrayList<>();
        for (Goods goods : goodsPage.getContent()) {
            goods.setGoodsSkus(skusGroupByGoodsId.get(goods.getId()));
            GoodsResp goodsResp = new GoodsResp();
            BeanUtils.copyProperties(goods, goodsResp);
            resps.add(goodsResp);
        }

        return new JSONResult(goodsPage, pageable.getPageNumber()).put("list", resps);
    }

    @SuppressWarnings("unchecked")
    @RequestMapping(value = "/goods/insert")
    @Secured("ROLE_GOODS_INSERT")
    @Transactional(rollbackFor = Exception.class)
    public JSONResult add(@RequestParam(value = "params") String params) {
        JSONObject data = JSONObject.fromObject(params);

        Goods goods = new Goods();

        // 基本信息保存
        goods.setCategoryId(data.getLong("categoryId"));
        goods.setName(data.getString("name"));
        goods.setThumb(data.getString("thumb"));
        goods.setSellingPrice(data.getInt("sellingPrice"));
        goods.setMarketPrice(data.getInt("marketPrice"));
        goods.setHasMultiSku(data.getBoolean("hasMultiSku"));
        goods.setStatus(Constants.GOODS_STATUS_LOWER);// 添加商品默认为下架状态
        goods.setDetail(data.optString("body", ""));
        goods.setRuleId(Constants.GOODS_TYPE_REALITY); // 实物类型，必须设置，不然有bug，导致值为0

        // 商品编号
        String goodsNo = data.optString("goodsNo");
        if (Strings.isBlank(goodsNo)) {
            do {
                goodsNo = RandomStringGenerateHelper.getRandomString(8);
            } while (goodsRepository.existsByGoodsNo(goodsNo));
        } else {
            if (goodsRepository.existsByGoodsNo(goodsNo)) {
                return new JSONResult(ErrorCode.DUPLICATE_KEY, "商品编号已存在");
            }
        }
        goods.setGoodsNo(goodsNo);

        // 轮播图
        JSONArray slideImages = data.getJSONArray("slideImages");
        saveSlideImages(goods, slideImages);

        goodsRepository.save(goods);

        List<GoodsSku> oldSkus = goodsSkuRepository.findByGoodsIdOnLock(goods.getId());

        List<GoodsAttrName> attrs = saveAttrs(goods, data.getJSONArray("attrs"));
        saveSku(goods, data.getJSONArray("sku"), oldSkus, attrs);


        // 商品标签
        JSONArray goodsTagsJson = data.getJSONArray("goodsTags");
        saveTags(goods, goodsTagsJson);

        return new JSONResult().put("count", 1).put("model", data);
    }


    @SuppressWarnings("unchecked")
    @RequestMapping(value = "/goods/update")
    @Secured("ROLE_GOODS_UPDATE")
    @Transactional(rollbackFor = Exception.class)
    public JSONResult update(@RequestParam(value = "params") String params) {
        JSONObject data = JSONObject.fromObject(params);

        Long goodsId = data.getLong("id");
        Goods goods = goodsRepository.findByIdOnLock(goodsId);
        if (goods == null) {
            return new JSONResult(ErrorCode.NO_DATA, "商品不存在");
        }

        Goods oldGoods = goodsService.findById(goodsId);

        // 基本信息保存
        goods.setCategoryId(data.getLong("categoryId"));
        goods.setName(data.getString("name"));
        goods.setThumb(data.getString("thumb"));
        goods.setSellingPrice(data.getInt("sellingPrice"));
        goods.setMarketPrice(data.getInt("marketPrice"));
        goods.setHasMultiSku(data.getBoolean("hasMultiSku"));
        goods.setStatus(Constants.GOODS_STATUS_LOWER);
        goods.setDetail(data.optString("body", ""));
        goods.setUpdateTime(DateHelper.getStringDate());

        // 商品编号
        String goodsNo = data.optString("goodsNo");
        if (Strings.isBlank(goodsNo)) {
            do {
                goodsNo = RandomStringGenerateHelper.getRandomString(8);
            } while (goodsRepository.existsByGoodsNo(goodsNo));
        } else {
            Goods res = goodsRepository.findByGoodsNo(goodsNo);
            if (res != null && !res.getGoodsNo().equals(goods.getGoodsNo())) {
                return new JSONResult(ErrorCode.DUPLICATE_KEY, "商品编号已存在");
            }
        }
        goods.setGoodsNo(goodsNo);

        // 轮播图
        JSONArray slideImages = data.getJSONArray("slideImages");
        saveSlideImages(goods, slideImages);

        goodsRepository.save(goods);

        // 规格和sku
        List<GoodsSku> oldSkus = goodsSkuRepository.findByGoodsIdOnLock(goods.getId());

        List<GoodsAttrName> attrs = saveAttrs(goods, data.getJSONArray("attrs"));
        List<GoodsSku> deletedSku = saveSku(goods, data.getJSONArray("sku"), oldSkus, attrs);

        // 库存操作
        List<Map<String, Object>> oldData = new ArrayList<>();
        List<Map<String, Object>> changeData = new ArrayList<>();
        int totalDeletedStock = 0;
        String stockRemark = "";
        String type = "";
        if (oldSkus.size() == 0 && data.getJSONArray("sku").size() > 0 && goods.getStock() > 0) {
            //原商品没有SKU，但有库存，增加SKU后删除原库存
            totalDeletedStock = goods.getStock();

            Map<String, Object> old = new HashMap<>();
            old.put("skuId", 0);
            old.put("value", goods.getStock());
            oldData.add(old);

            Map<String, Object> newObj = new HashMap<>();
            newObj.put("skuId", 0);
            newObj.put("value", goods.getStock());
            changeData.add(newObj);

            type = "del";
            stockRemark = "添加商品规格，删除旧库存";
        } else {
            if (deletedSku.size() > 0) {
                for (GoodsSku sku : deletedSku) {
                    if (sku.getStock() > 0) {
                        totalDeletedStock += sku.getStock();
                        Map<String, Object> old = new HashMap<>();
                        old.put("skuId", sku.getId());
                        old.put("value", sku.getStock());
                        oldData.add(old);

                        Map<String, Object> newObj = new HashMap<>();
                        newObj.put("skuId", sku.getId());
                        newObj.put("value", sku.getStock());
                        changeData.add(newObj);
                    }
                }
                type = "del";
                stockRemark = "删除商品规格";
            }
        }

        if (oldData.size() > 0) {
            ObjectMapper mapper = new ObjectMapper();
            GoodsStockLog stockLog = new GoodsStockLog();
            try {
                stockLog.setOldData(mapper.writeValueAsString(oldData));
                stockLog.setChangeData(mapper.writeValueAsString(changeData));
            } catch (JsonProcessingException e) {
                log.error("商品操作日志保存失败：" + e.getMessage());
                e.printStackTrace();
            }
            stockLog.setUid(AuthorizeHelper.getUser().getId());
            stockLog.setRealname(AuthorizeHelper.getUser().getRealname());
            stockLog.setGoodsId(goods.getId());
            stockLog.setType(type);
            stockLog.setRemark(stockRemark);

            goodsStockLogRepository.save(stockLog);

            goods.setStock(goods.getStock() - totalDeletedStock);
        }


        // 商品标签
        JSONArray goodsTagsJson = data.getJSONArray("goodsTags");
        saveTags(goods, goodsTagsJson);

        // sku 改变，商品变成待审核状态
        Goods newGoods = goodsService.findById(goodsId);
        List<GoodsSku> newSkus = goodsSkuRepository.findByGoodsId(goodsId);

        // SKU 修改，商品变为待审核
        if (!newSkus.toString().equals(oldSkus.toString())) {
            newGoods.setExamineStatus(Constants.GOODS_EXAMINE_WAIT);
            saveExamineLog(newGoods, "商品修改了SKU");

            goodsRepository.save(newGoods);
        }

        return new JSONResult().put("count", 1).put("model", data);
    }


    /**
     * 保存商品轮播图
     *
     * @param goods
     * @param slideImages
     */
    private void saveSlideImages(Goods goods, List<JSONObject> slideImages) {
        if (slideImages.size() == 0) {
            return;
        }
        List<GoodsPicture> goodsPictureList = new ArrayList<>();
        for (Object image : slideImages) {
            GoodsPicture goodsPicture = new GoodsPicture();
            goodsPicture.setUrl(image.toString());
            goodsPictureList.add(goodsPicture);
        }
        goods.getGoodsPictures().clear();
        goods.getGoodsPictures().addAll(goodsPictureList);
    }

    /**
     * 保存商品标签和商品的关联
     *
     * @param goods
     * @param goodsTagsJson
     */
    private void saveTags(Goods goods, List<Integer> goodsTagsJson) {
        if (goodsTagsJson.size() > 0) {
//            // 解除原有关联
//            List<GoodsTag> goodsTags = goodsTagRepository.findAll();
//            for (GoodsTag tag : goodsTags) {
//                tag.getGoodsList().remove(goods);
//            }

            List<Long> goodsTagIds = new ArrayList<>();
            for (int tag : goodsTagsJson) {
                goodsTagIds.add(Long.parseLong(String.valueOf(tag)));
            }
            List<GoodsTag> goodsTagList = goodsTagRepository.findByIdIn(goodsTagIds);
            goods.getTags().clear();
            goods.getTags().addAll(goodsTagList);

//            for (GoodsTag goodsTag : goodsTagList) {
//                goodsTag.getGoodsList().add(goods);
//                goodsTagRepository.save(goodsTag);
//            }
        }
    }

    /**
     * 根据商品id获取商品信息
     *
     * @param goodsId
     * @return
     */
    @RequestMapping(value = "/goods/getGoodsInfo")
    public JSONResult getGoodsInfo(@RequestParam(value = "id") Long goodsId) {
        Goods goods = goodsService.findById(goodsId);

        if (goods == null) {
            return new JSONResult(ErrorCode.NO_DATA, "商品不存在");
        }

        return new JSONResult().put("goods", goods);
    }

    /**
     * 获取配置信息
     *
     * @return
     */
    @RequestMapping(value = "/goods/schema")
    public JSONResult schema() {
        // querySchema
        List<SchemaResp> querySchema = new ArrayList<>();

        // 商品分类
        SchemaResp categoriesObj = new SchemaResp();
        List<Map> options = new ArrayList<>();

        List<Map> categories = goodsCategoryService.getFormattedTypes(goodsCategoryService.getTree2());
        for (Map category : categories) {
            Map<String, Object> item = new HashMap<>();
            item.put("key", category.get("id"));
            item.put("value", category.get("name"));
            options.add(item);
        }

        categoriesObj.setKey("search_eq_categoryId");
        categoriesObj.setTitle("商品分类");
        categoriesObj.setDataType("varchar");
        categoriesObj.setShowType("select");
        categoriesObj.setOptions(options);

        querySchema.add(categoriesObj);

        // 商品标签
        SchemaResp tagsObj = new SchemaResp();
        List<Map> options2 = new ArrayList<>();
        List<GoodsTag> goodsTags = goodsTagRepository.findAll();
        for (GoodsTag goodsTag : goodsTags) {
            Map<String, Object> item = new HashMap<>();
            item.put("key", goodsTag.getId());
            item.put("value", goodsTag.getTitle());
            options2.add(item);
        }

        tagsObj.setKey("search_eq_tagsId");
        tagsObj.setTitle("商品标签");
        tagsObj.setDataType("varchar");
        tagsObj.setShowType("select");
        tagsObj.setOptions(options2);

        querySchema.add(tagsObj);

        // dataSchema
        List<SchemaResp> dataSchema = new ArrayList<>();

        SchemaResp categoriesObj2 = new SchemaResp();
        categoriesObj2.setKey("categoryId");
        categoriesObj2.setTitle("商品分类");
        categoriesObj2.setDataType("varchar");
        categoriesObj2.setShowType("select");
        categoriesObj2.setOptions(options);

        dataSchema.add(categoriesObj2);

        return new JSONResult().put("querySchema", querySchema).put("dataSchema", dataSchema);
    }

    /**
     * 图片oss上传
     *
     * @param file
     * @return
     */
    @RequestMapping(value = "/goods/uploadImage")
    @Secured("ROLE_GOODS_UPLOAD_IMAGE")
    public JSONResult uploadImage(@Valid MultipartFile file) {
        // 实例化oss对象
        OSSClientUtils ossClient = new OSSClientUtils(ENDPOINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET, BUCKET_NAME, FILE_DIR);
        String name = ossClient.uploadImg2Oss(file);
        String imgUrl = ossClient.getImgUrl(name);

        // 销毁对象
        ossClient.destory();

        return new JSONResult().put("url", imgUrl);
    }

    /**
     * 商品审核操作
     *
     * @param examine
     * @param goodsId
     * @return
     */
    @Secured("ROLE_GOODS_EXAMINE")
    @RequestMapping(value = "/goods/changeExamine")
    public JSONResult changeExamine(@RequestParam(value = "examine") Integer examine,
                                    @RequestParam(value = "goodsId") Long goodsId) {
        Goods goods = goodsService.findById(goodsId);

        if (goods == null) {
            return new JSONResult(ErrorCode.INVALID_PARAM, "商品ID错误");
        }

        if (goods.getExamineStatus() == examine) {
            return new JSONResult(ErrorCode.INVALID_PARAM, "审核状态错误");
        }

        if (goods.getExamineStatus() != examine) {
            goods.setExamineStatus(examine);
            saveExamineLog(goods);
            goodsRepository.save(goods);
        }


        return new JSONResult().put("model", goods);
    }

    /**
     * 商品上下架操作
     *
     * @param status
     * @param goodsId
     * @return
     */
    @Secured("ROLE_GOODS_SHELVES")
    @RequestMapping(value = "/goods/changeStatus")
    public JSONResult changeStatus(@RequestParam(value = "status") Integer status,
                                   @RequestParam(value = "goodsId") Long goodsId) {
        Goods goods = goodsService.findById(goodsId);

        if (goods == null) {
            return new JSONResult(ErrorCode.INVALID_PARAM, "商品ID错误");
        }

        if (goods.getExamineStatus() != Constants.GOODS_EXAMINE_NORMAL) {
            return new JSONResult(ErrorCode.STATUS_ERROR, "商品没有通过审核");
        }

        goods.setStatus(status);
        goodsRepository.save(goods);


        return new JSONResult().put("model", goods);
    }

    /**
     * 商品入库和出库操作
     *
     * @param body
     * @return
     * @throws AppException
     */
    @RequestMapping(value = "/goods/simpleStockEdit")
    @Secured("ROLE_GOODS_SIMPLE_STOCK_UPDATE")
    @SuppressWarnings("unchecked")
    @Transactional(rollbackFor = Exception.class)
    public JSONResult simpleStockEdit(@RequestParam String body) throws AppException {
        JSONObject params = JSONObject.fromObject(body);

        Goods goods = goodsRepository.findByIdOnLock(params.getLong("goodsId"));
        if (goods == null) {
            return new JSONResult(ErrorCode.NO_DATA, "商品ID错误");
        }

        List<JSONObject> changeData = (List<JSONObject>) params.get("opData");
        String opType = params.getString("type");

        // 获取SKU数据
        List<GoodsSku> skus = goodsSkuRepository.findByGoodsIdOnLock(goods.getId());
        Map<Long, GoodsSku> goodsSkuMap = CollectionUtils.columnMap(skus, GoodsSku::getId);
        List<GoodsSku> oldSkus = new ArrayList<>();

        List<Map> oldData = new ArrayList<>();
        int total = 0; // 总库存

        if (skus.size() > 0) {
            //有SKU
            for (JSONObject data : changeData) {
                if (goodsSkuMap.containsKey(data.getLong("skuId"))) {
                    GoodsSku oldSku = goodsSkuMap.get(data.getLong("skuId"));

                    Map<String, Object> old = new HashMap<>();
                    old.put("skuId", oldSku.getId());
                    old.put("value", oldSku.getStock());

                    oldData.add(old);

                    if (opType.equalsIgnoreCase("in")) {
                        oldSku.setStock(oldSku.getStock() + data.getInt("value"));
                    } else {
                        oldSku.setStock(oldSku.getStock() - data.getInt("value"));
                    }

                    if (oldSku.getStock() < 0) {
                        // 必须抛出异常，事务才能回滚
                        throw new AppException(ErrorCode.INVALID_PARAM, "扣除库存大于现有库存");
                    }
                    oldSkus.add(oldSku);
                    total += (Integer) data.get("value");
                }
            }
        } else {
            //无SKU
            Map<String, Object> old = new HashMap<>();
            old.put("skuId", 0);
            old.put("value", goods.getStock());
            oldData.add(old);

            total = changeData.get(0).getInt("value");
        }

        if (opType.equalsIgnoreCase("in")) {
            goods.setStock(goods.getStock() + total);
        } else {
            goods.setStock(goods.getStock() - total);
        }

        if (goods.getStock() < 0) {
            throw new AppException(ErrorCode.INVALID_PARAM, "扣除库存大于现有库存");
        }

        goodsSkuRepository.saveAll(oldSkus);
        goodsRepository.save(goods);

        // 保存库存操作日志
        GoodsStockLog log = new GoodsStockLog();
        log.setOldData(oldData.toString());
        log.setChangeData(changeData.toString());
        log.setUid(AuthorizeHelper.getUser().getId());
        log.setRealname(AuthorizeHelper.getUser().getRealname());
        log.setGoodsId(goods.getId());
        log.setType(opType);
        log.setRemark((String) params.get("remark"));
        goodsStockLogRepository.save(log);

        return new JSONResult();
    }

    /**
     * 商品伪删除
     *
     * @param keys
     * @return
     */
    @RequestMapping(value = "/goods/delete")
    @Secured("ROLE_GOODS_PSEUDO_DELETE")
    public JSONResult pseudoDelete(@RequestParam String keys) {
        if (StringUtils.isBlank(keys)) {
            return new JSONResult(ErrorCode.NO_DATA, "参数错误");
        }
        String[] ids = keys.split(",");
        Map<Long, Goods> goodsMap = CollectionUtils.columnMap(goodsRepository.findAll(), Goods::getId);
        List<Goods> goodsList = new ArrayList<>();
        for (String id : ids) {
            Goods goods = goodsMap.get(Long.parseLong(id));
            if (goods == null) {
                return new JSONResult(ErrorCode.NO_DATA, "商品不存在");
            }
            goods.setExamineStatus(Constants.GOODS_EXAMINE_WAIT);
            goods.setStatus(Constants.GOODS_STATUS_NORMAL);
            goods.setIsDeleted(true);

            goodsList.add(goods);
        }
        goodsRepository.saveAll(goodsList);

        return new JSONResult().put("count", goodsList.size()).put("ids", ids);
    }

    /**
     * 保存属性
     *
     * @param goods
     * @param attrs
     * @return
     */
    @SuppressWarnings("unchecked")
    private List<GoodsAttrName> saveAttrs(Goods goods, List<JSONObject> attrs) {
        List<GoodsAttrName> goodsAttrNames = new ArrayList<>();

        // 删除原有的属性
        goodsAttrNameRepository.deleteByGoodsId(goods.getId());

        for (JSONObject attr : attrs) {
            // 属性名
            GoodsAttrName goodsAttrName = new GoodsAttrName();
            goodsAttrName.setName(attr.getString("name"));
            goodsAttrName.setKey(attr.getInt("key"));
            goodsAttrName.setGoodsId(goods.getId());

            Set<GoodsAttrValue> goodsAttrValues = new HashSet<>();
            List<JSONObject> attrValues = attr.getJSONArray("goodsAttrValues");

            for (JSONObject attrValue : attrValues) {
                // 属性值
                GoodsAttrValue goodsAttrValue = new GoodsAttrValue();

                goodsAttrValue.setValue(attrValue.getString("value"));
                goodsAttrValue.setThumb(attrValue.getString("thumb"));
                goodsAttrValue.setIsUsed(attrValue.getBoolean("isUsed"));
                goodsAttrValue.setKey(attrValue.getInt("key"));
                goodsAttrValue.setGoodsId(goods.getId());

                goodsAttrValues.add(goodsAttrValue);
            }
            goodsAttrName.setGoodsAttrValues(goodsAttrValues);

            goodsAttrNames.add(goodsAttrName);
        }

        goodsAttrNameRepository.saveAll(goodsAttrNames);

        return goodsAttrNames;
    }

    /**
     * 保存SKU
     *
     * @param goods
     * @param attrs
     * @param skus
     * @return
     */
    @SuppressWarnings("unchecked")
    private List<GoodsSku> saveSku(Goods goods, List<JSONObject> skus, List<GoodsSku> oldSkus, List<GoodsAttrName> attrs) {
        Map<Long, GoodsSku> oldSkuMap = CollectionUtils.columnMap(oldSkus, GoodsSku::getId);

        List<GoodsSku> goodsSkus = new ArrayList<>();
        //删除无效的SKU
        List<GoodsSku> willDeleted;

        List<Long> skuIds = new ArrayList<>();
        for (JSONObject sku : skus) {
            if (sku.optLong("id", 0) != 0) {
                skuIds.add(sku.getLong("id"));
            }
        }

        if (skuIds.size() > 0) {
            willDeleted = goodsSkuRepository.findByGoodsIdAndIdNotIn(goods.getId(), skuIds);
        } else {
            willDeleted = oldSkus;
        }


        // 保存SKU
        for (JSONObject sku : skus) {
            GoodsSku goodsSku;
            if (sku.optLong("id", 0) != 0) {
                goodsSku = oldSkuMap.get(sku.getLong("id"));
            } else {
                goodsSku = new GoodsSku();
            }

            goodsSku.setGoodsId(goods.getId());
            goodsSku.setAttrValues(getAttrValuesDataStr(sku, attrs));
            goodsSku.setMarketPrice(sku.getLong("marketPrice"));
            goodsSku.setSellingPrice(sku.getLong("sellingPrice"));
            goodsSku.setSkuDesc(sku.getString("skuDesc"));
            goodsSku.setSkuDetail(sku.getString("skuDetail"));

            if (sku.optLong("id", 0) == 0) {
                goodsSkus.add(goodsSku);
            }
        }

        goodsSkuRepository.deleteAll(willDeleted);
        goodsSkuRepository.saveAll(goodsSkus);

        return willDeleted;
    }

    /**
     * 获取SKU的属性名和属性值对应表
     *
     * @param sku
     * @param attrs
     * @return
     */
    private String getAttrValuesDataStr(JSONObject sku, List<GoodsAttrName> attrs) {
        //keyMap为前端数据构造好的，key为前端生成的唯一数字，非ID
        JSONObject keyMap = sku.getJSONObject("keyMap");

        ArrayList<String> parts = new ArrayList<>();
        for (Object key : keyMap.keySet()) {
            parts.add(getAttrValuesDataStrPart(Integer.valueOf(key.toString()), keyMap.getInt(key.toString()), attrs));
        }

        return "[" + Strings.join(parts, ',') + "]";
    }

    private String getAttrValuesDataStrPart(int attrNameKey, int attrValueKey, List<GoodsAttrName> attrs) {
        String result = "";
        for (GoodsAttrName attr : attrs) {
            if (attr.getKey() == attrNameKey) {
                result = attr.getId() + ":";
                for (GoodsAttrValue value : attr.getGoodsAttrValues()) {
                    if (value.getKey() == attrValueKey) {
                        result += value.getId();
                        return result;
                    }
                }
            }
        }
        return result;
    }

    /**
     * 保存商品审核日志
     *
     * @param goods
     */
    private void saveExamineLog(Goods goods) {
        saveExamineLog(goods, "");
    }

    private void saveExamineLog(Goods goods, String remark) {
        AdminUser user = AuthorizeHelper.getUser();

        GoodsExamineLog goodsExamineLog = new GoodsExamineLog();
        goodsExamineLog.setUid(user.getId());
        goodsExamineLog.setRealname(user.getRealname());
        goodsExamineLog.setGoodsName(goods.getName());
        goodsExamineLog.setStatus(goods.getExamineStatus());
        goodsExamineLog.setRemark(remark);

        goods.getExamineLogs().add(goodsExamineLog);
    }
}
